package Controller

import (
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"sync"
	"time"
	"web_back_go/Common"
	"web_back_go/DAO/gorm"
	"web_back_go/DAO/gorm/GormModel"
	"web_back_go/Dto"
	"web_back_go/Response"
)

/*
GetCartProdCount
@Description: 获取购物车商品数量
*/
func GetCartProdCount(c *gin.Context) {
	//从请求头中获取用户token
	token := c.GetHeader("Authorization")
	if token == "" {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}
	userId, _, err := Common.CodeToken(token)
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}
	db := gorm.Db
	var count int64
	db.Table("tz_basket").Where("user_id = ?", userId).Count(&count)

	c.JSON(200, Response.ResponseBody{
		Code:    "00000",
		Data:    count,
		Success: true,
		Msg:     nil,
	})
}

//获取购物车失效没写 url ；/p/shopCart/expiryProdList

// ShopCartParam 结构体用于表示购物车相关参数
type ShopCartParam struct {
	// 购物项id，对应Java代码中的Long类型，在Go中使用int64表示长整型
	BasketId int64 `json:"basketId" comment:"购物项id"`
	// 活动id，传0则不参与该活动，同样对应Java中的Long类型，在Go中用int64表示
	DiscountId int64 `json:"discountId" comment:"活动id,传0则不参与该活动"`
}

/*
GetShopCartItemByUserId
获取用户的购物车商品列表
*/
func GetShopCartItemByUserId(c *gin.Context) {
	var basketIdShopCartParamMap map[int64]ShopCartParam
	if err := c.ShouldBindJSON(&basketIdShopCartParamMap); err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: false,
			Msg:     "服务器错误",
		})
		return
	}
	//从请求头中获取用户token
	token := c.GetHeader("Authorization")
	userId, _, err := Common.CodeToken(token)
	if token == "" || err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}
	db := gorm.Db.Begin()

	//确保事务回滚或者提交事务
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()
	// 更新购物车信息
	if basketIdShopCartParamMap != nil {
		/*
		   <update id="updateDiscountItemId">
		        <foreach collection="basketIdShopCartParamMap" index="key" item="shopCartParam" separator=";">
		            UPDATE tz_basket SET discount_id = #{shopCartParam.discountId} where basket_id = #{key} and user_id = #{userId}
		        </foreach>
		    </update>
		*/
		for basketId, shopCartParam := range basketIdShopCartParamMap {
			result := db.Model(&GormModel.TZBasket{}).
				Where("basket_id = ? AND user_id = ?", basketId, userId).
				Update("discount_id", shopCartParam.DiscountId)
			if result.Error != nil {
				err = result.Error
				return
			}
		}
	}
	// 拿到购物车的所有item
	/*
	   SELECT tb.*,tb.basket_count as prod_count,tsd.shop_name,IFNULL(ts.pic,tp.pic)AS pic,ts.price,ts.ori_price,tp.brief,ts.properties,ts.prod_name,ts.sku_name
	       FROM tz_basket tb
	       LEFT JOIN tz_shop_detail tsd ON tb.shop_id = tsd.shop_id
	       LEFT JOIN tz_prod tp ON tb.prod_id = tp.prod_id
	       LEFT JOIN tz_sku ts ON tb.sku_id = ts.sku_id
	       WHERE tp.status = 1 AND ts.status =1 AND tb.user_id = #{userId}
	       ORDER BY tb.`basket_id` DESC
	*/
	var shopCartItemDtoList []Dto.ShopCartItemDto
	err = db.Raw(`
		SELECT tb.*, tb.basket_count as prod_count, tsd.shop_name, IFNULL(ts.pic, tp.pic) AS pic, ts.price, ts.ori_price, tp.brief, ts.properties, ts.prod_name, ts.sku_name
		FROM tz_basket tb
		LEFT JOIN tz_shop_detail tsd ON tb.shop_id = tsd.shop_id
		LEFT JOIN tz_prod tp ON tb.prod_id = tp.prod_id
		LEFT JOIN tz_sku ts ON tb.sku_id = ts.sku_id
		WHERE tp.status = 1 AND ts.status = 1 AND tb.user_id = ?
		ORDER BY tb.basket_id DESC
	`, userId).Scan(&shopCartItemDtoList).Error
	res := GetShopCarts(shopCartItemDtoList)
	c.JSON(200, Response.ResponseBody{
		Code:    "00000",
		Data:    res,
		Success: true,
		Msg:     nil,
	})
}

/*
GetShopCarts
根据购物车商品列表构建购物车DTO列表
*/
func GetShopCarts(shopCartItems []Dto.ShopCartItemDto) []Dto.ShopCartDto {
	// 根据店铺ID划分item
	shopCartMap := make(map[int64][]Dto.ShopCartItemDto)
	for _, shopCartItemDto := range shopCartItems {
		shopCartMap[shopCartItemDto.ShopId] = append(shopCartMap[shopCartItemDto.ShopId], shopCartItemDto)
	}

	// 返回一个店铺的所有信息
	var shopCartDtos []Dto.ShopCartDto
	for shopId, shopCartItemDtoList := range shopCartMap {
		// 获取店铺的所有商品项
		// 构建每个店铺的购物车信息
		var shopCart Dto.ShopCartDto
		// 店铺信息
		shopCart.ShopId = shopId

		if len(shopCartItemDtoList) > 0 {
			shopCart.ShopName = shopCartItemDtoList[0].ShopName
		}

		// 构建 ShopCartItemDiscountDto
		var shopCartItemDiscountDto Dto.ShopCartItemDiscountDto
		shopCartItemDiscountDto.ShopCartItems = shopCartItemDtoList

		// 假设 ChooseDiscountItemDto 是空的，或者你需要从其他地方获取
		shopCartItemDiscountDto.ChooseDiscountItemDto = Dto.ChooseDiscountItemDto{}

		// 将 ShopCartItemDiscountDto 添加到 ShopCartDto
		shopCart.ShopCartItemDiscounts = append(shopCart.ShopCartItemDiscounts, shopCartItemDiscountDto)

		// 将 ShopCartDto 添加到 shopCartDtos
		shopCartDtos = append(shopCartDtos, shopCart)
	}

	return shopCartDtos
}

type ChangeShopCartParam struct {
	BasketId           int64  `json:"basketId" validate:"required"`
	ProdId             int64  `json:"prodId" validate:"required"`
	SkuId              int64  `json:"skuId" validate:"required"`
	ShopId             int64  `json:"shopId" validate:"required"`
	Count              int    `json:"count" validate:"required"`
	DistributionCardNo string `json:"distributionCardNo"`
}

/*
AddCartItem

	@Operation(summary = "添加、修改用户购物车物品", description = "通过商品id(prodId)、skuId、店铺Id(shopId),添加/修改用户购物车商
			品，并传入改变的商品个数(count)，" +
	        "当count为正值时，增加商品数量，当count为负值时，将减去商品的数量，当最终count值小于0时，会将商品从购物车里面删除")
*/
func AddCartItem(c *gin.Context) {
	var param ChangeShopCartParam
	if err := c.ShouldBindJSON(&param); err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "参数错误",
		})
		return
	}
	log.Printf("param: %v\n", param)

	if param.Count == 0 {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "请输入更改数量",
		})
		return
	}

	//从请求头中获取用户token
	token := c.GetHeader("Authorization")
	if token == "" {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}
	userId, _, err := Common.CodeToken(token)
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}

	db := gorm.Db.Begin()

	// 确保事务最终会被提交或回滚
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()

	var shopCartItemDtoList []Dto.ShopCartItemDto
	err = db.Raw("SELECT tb.*,tb.basket_count as prod_count,tsd.shop_name,IFNULL(ts.pic,tp.pic)AS pic,ts.price,ts.ori_price,tp.brief,ts.properties,ts.prod_name,ts.sku_name "+
		"FROM tz_basket tb "+
		"LEFT JOIN tz_shop_detail tsd ON tb.shop_id = tsd.shop_id "+
		"LEFT JOIN tz_prod tp ON tb.prod_id = tp.prod_id "+
		"LEFT JOIN tz_sku ts ON tb.sku_id = ts.sku_id "+
		"WHERE tp.status = 1 AND ts.status =1 AND tb.user_id =? "+
		"ORDER BY tb.`basket_id` DESC", userId).Scan(&shopCartItemDtoList).Error
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "服务器异常",
		})
		return
	}

	// 计算每个商品总价
	for i := range shopCartItemDtoList {
		shopCartItemDtoList[i].ProductTotalAmount = float64(shopCartItemDtoList[i].ProdCount) * shopCartItemDtoList[i].Price
	}

	var prodParam GormModel.TzProd
	var skuParam GormModel.TzSku
	err = db.Model(&GormModel.TzProd{}).Where("prod_id = ?", param.ProdId).First(&prodParam).Error
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "商品信息查询失败",
		})
		return
	}

	err = db.Model(&GormModel.TzSku{}).Where("sku_id = ?", param.SkuId).First(&skuParam).Error
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "SKU信息查询失败",
		})
		return
	}

	// 当商品状态不正常时，不能添加到购物车
	if *prodParam.Status != 1 || *skuParam.Status != 1 {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "当前商品已下架",
		})
		return
	}

	for _, shopCartItemDto := range shopCartItemDtoList {
		if param.SkuId == shopCartItemDto.SkuId {
			var basket GormModel.TZBasket
			basket.UserId = userId
			basket.BasketCount = param.Count + shopCartItemDto.ProdCount

			// 防止购物车变成负数
			if basket.BasketCount < 0 {
				result := db.Where("user_id = ? AND basket_id = ?", userId, shopCartItemDto.BasketId).Delete(&GormModel.TZBasket{})
				if result.Error != nil {
					err = result.Error
					return
				}
				c.JSON(200, Response.ResponseBody{
					Code:      "00000",
					Data:      nil,
					Success:   true,
					Msg:       nil,
					Timestamp: time.Now().Unix(),
				})
				return
			}

			// 当sku实际库存不足时，不能添加到购物车
			if *skuParam.Stocks < basket.BasketCount && shopCartItemDto.ProdCount > 0 {
				c.JSON(200, Response.ResponseBody{
					Code:    "A00001",
					Data:    nil,
					Success: true,
					Msg:     "当前商品库存不足",
				})
				return
			}

			// 更新购物车数量
			result := db.Model(&GormModel.TZBasket{}).Where("basket_id = ?", shopCartItemDto.BasketId).Updates(map[string]interface{}{
				"user_id":      userId,
				"basket_count": basket.BasketCount,
			})
			if result.Error != nil {
				err = result.Error
				return
			}

			c.JSON(200, Response.ResponseBody{
				Code:      "00000",
				Data:      "ok",
				Success:   true,
				Msg:       nil,
				Sign:      nil,
				Timestamp: time.Now().Unix(),
			})
			return
		}
	}

	// 防止购物车已被删除的情况下,添加了负数的商品
	if param.Count < 0 {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "商品已从购物车移除",
		})
		return
	}
	// 当sku实际库存不足时，不能添加到购物车
	if *skuParam.Stocks < param.Count {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "库存不足",
		})
		return
	}
	// 所有都正常时
	//basketService.addShopCartItem(param,userId);
	err = db.Model(&GormModel.TZBasket{}).Create(&GormModel.TZBasket{
		BasketCount:        param.Count,
		BasketDate:         time.Now(),
		ProdId:             param.ProdId,
		ShopId:             param.ShopId,
		UserId:             userId,
		SkuId:              param.SkuId,
		DistributionCardNo: param.DistributionCardNo,
	}).Error
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "服务器异常",
		})
		return
	}
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Data:      "ok",
		Success:   true,
		Msg:       nil,
		Sign:      nil,
		Timestamp: time.Now().Unix(),
	})
}

// ShopCartAmountDto 结构体用于表示购物车合计相关信息
type ShopCartAmountDto struct {
	TotalMoney    float64 `json:"totalMoney"`
	FinalMoney    float64 `json:"finalMoney"`
	SubtractMoney float64 `json:"subtractMoney"`
	Count         int     `json:"count"`
}

func GetTotalPay(c *gin.Context) {
	var basketIds []int64
	if err := c.ShouldBindJSON(&basketIds); err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "参数错误",
		})
		return
	}

	// 从请求头中获取用户token
	token := c.GetHeader("Authorization")
	if token == "" {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}
	userId, _, err := Common.CodeToken(token)
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}

	db := gorm.Db
	var dbShopCartItems []Dto.ShopCartItemDto
	err = db.Raw("SELECT tb.*,tb.basket_count as prod_count,tsd.shop_name,IFNULL(ts.pic,tp.pic)AS pic,ts.price,ts.ori_price,tp.brief,ts.properties,ts.prod_name,ts.sku_name "+
		"FROM tz_basket tb "+
		"LEFT JOIN tz_shop_detail tsd ON tb.shop_id = tsd.shop_id "+
		"LEFT JOIN tz_prod tp ON tb.prod_id = tp.prod_id "+
		"LEFT JOIN tz_sku ts ON tb.sku_id = ts.sku_id "+
		"WHERE tp.status = 1 AND ts.status =1 AND tb.user_id =? "+
		"ORDER BY tb.`basket_id` DESC", userId).Scan(&dbShopCartItems).Error
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "服务器异常",
		})
		return
	}

	for i, shopCartItemDto := range dbShopCartItems {
		productTotalAmount := float64(shopCartItemDto.ProdCount) * shopCartItemDto.Price
		dbShopCartItems[i].ProductTotalAmount = productTotalAmount
	}

	chooseShopCartItems := SelectShopCartItems(dbShopCartItems, basketIds)

	shopCartMap := make(map[int64][]Dto.ShopCartItemDto)
	for _, item := range chooseShopCartItems {
		shopCartMap[item.ShopId] = append(shopCartMap[item.ShopId], item)
	}

	total := float64(0)
	count := 0
	reduce := float64(0)

	for shopId := range shopCartMap {
		shopCartItemDtoList := shopCartMap[shopId]
		var shopCart Dto.ShopCartDto
		shopCart.ShopId = shopId

		var shopCartItemDiscountDto Dto.ShopCartItemDiscountDto
		shopCartItemDiscountDto.ShopCartItems = shopCartItemDtoList
		shopCartItemDiscountDto.ChooseDiscountItemDto = Dto.ChooseDiscountItemDto{}

		shopCart.ShopCartItemDiscounts = append(shopCart.ShopCartItemDiscounts, shopCartItemDiscountDto)

		for _, shopCartItemDiscount := range shopCart.ShopCartItemDiscounts {
			shopCartItems := shopCartItemDiscount.ShopCartItems

			for _, shopCartItem := range shopCartItems {
				count += shopCartItem.ProdCount
				total += shopCartItem.ProductTotalAmount
			}
		}
	}

	response := ShopCartAmountDto{
		TotalMoney:    total,
		FinalMoney:    total - reduce,
		SubtractMoney: reduce,
		Count:         count,
	}

	c.JSON(200, Response.ResponseBody{
		Code:    "00000",
		Data:    response,
		Success: true,
		Msg:     "Success",
	})
}

/*
SelectShopCartItemsThread
并发获取购物车商品信息
*/
func SelectShopCartItemsThread(shopCartItemDtoList []Dto.ShopCartItemDto, basketIds []int64) []Dto.ShopCartItemDto {
	var chooseShopCartItems []Dto.ShopCartItemDto
	var wg sync.WaitGroup
	resultChan := make(chan Dto.ShopCartItemDto, len(shopCartItemDtoList))

	// 创建一个 map 来存储 basketIds 以便快速查找
	basketIdSet := make(map[int64]struct{})
	for _, basketId := range basketIds {
		basketIdSet[basketId] = struct{}{}
	}

	// 使用 goroutine 并发处理每个 shopCartItemDto
	for _, item := range shopCartItemDtoList {
		wg.Add(1)
		go func(item Dto.ShopCartItemDto) {
			defer wg.Done()
			if _, exists := basketIdSet[item.BasketId]; exists {
				resultChan <- item
			}
		}(item)
	}

	// 启动一个 goroutine 来关闭 channel
	go func() {
		wg.Wait()
		close(resultChan)
	}()

	// 从 channel 中收集结果
	for item := range resultChan {
		chooseShopCartItems = append(chooseShopCartItems, item)
	}

	return chooseShopCartItems
}
func SelectShopCartItems(shopCartItemDtoList []Dto.ShopCartItemDto, basketIds []int64) []Dto.ShopCartItemDto {
	var chooseShopCartItems []Dto.ShopCartItemDto

	// 创建一个 map 来存储 basketIds 以便快速查找
	basketIdSet := make(map[int64]struct{})
	for _, basketId := range basketIds {
		basketIdSet[basketId] = struct{}{}
	}

	// 顺序遍历处理每个 shopCartItemDto
	for _, item := range shopCartItemDtoList {
		if _, exists := basketIdSet[item.BasketId]; exists {
			chooseShopCartItems = append(chooseShopCartItems, item)
		}
	}

	return chooseShopCartItems
}

/*
DelShopCartItem

	@Operation(summary = "删除用户购物车物品" , description = "通过购物车id删除用户购物车物品")
*/
func DelShopCartItem(c *gin.Context) {
	var basketIds []int64
	if err := c.ShouldBindJSON(&basketIds); err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "参数错误",
		})
		return
	}
	// 从请求头中获取用户token
	token := c.GetHeader("Authorization")
	userId, _, err := Common.CodeToken(token)
	if token == "" || err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}
	db := gorm.Db.Begin()
	//确保事务回滚或者提交事务
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()
	// 执行删除操作
	result := db.Where("user_id = ? AND basket_id IN ?", userId, basketIds).Delete(&GormModel.TZBasket{})
	if result.Error != nil {
		err = result.Error
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "已经删除",
		})
		return
	}

	if result.RowsAffected == 0 {

		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "已经删除",
		})
		return
	}

	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Data:      nil,
		Success:   true,
		Msg:       "ok",
		Version:   "1.0.0",
		Timestamp: time.Now().Unix(),
		Fail:      false,
	})
}

/*
DeleteAllShopCartItems
@Description: 根据用户ID,删除用户购物车所有物品
*/
func DeleteAllShopCartItems(c *gin.Context) {
	token := c.GetHeader("Authorization")
	userId, _, err := Common.CodeToken(token)
	if token == "" || err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00004",
			Data:    nil,
			Success: true,
			Msg:     "Unauthorized",
		})
		return
	}
	db := gorm.Db.Begin()
	//确保事务回滚或者提交事务
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()

	result := db.Where("user_id = ?", userId).Delete(&GormModel.TZBasket{})
	if result.Error != nil || result.RowsAffected == 0 {
		err = result.Error
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "已经删除",
		})
		return
	}
	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Data:      nil,
		Success:   true,
		Msg:       "ok",
		Version:   "1.0.0",
		Timestamp: time.Now().Unix(),
		Fail:      false,
	})
}
